package com.celesea.workflow.core.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.celesea.framework.authority.User;
import com.celesea.framework.entity.BaseEntity;
import com.celesea.framework.service.AbstractBaseService;
import com.celesea.framework.util.CollectionKit;
import com.celesea.framework.util.Const;
import com.celesea.framework.util.EnvUtil;
import com.celesea.framework.util.StringKit;
import com.celesea.workflow.component.AuthService;
import com.celesea.workflow.core.dao.WorkflowNodePermissionDao;
import com.celesea.workflow.core.entity.Workflow;
import com.celesea.workflow.core.entity.WorkflowNode;
import com.celesea.workflow.core.entity.WorkflowNodePermission;
import com.google.common.collect.Lists;
import net.sf.ehcache.hibernate.management.impl.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;

/**
 * @author JackYuan
 * @create 2017-11-28 12:53
 */
@Service
public class WorkflowNodePermissionServiceImpl extends
        AbstractBaseService<WorkflowNodePermission> implements WorkflowNodePermissionService {

    public static final String NAME = "name";
    public static final String JSON_OBJECT_PREFIX = "{";
    public static final String JSON_ARRAY_PREFIX = "[";
    @Autowired
    private WorkflowNodePermissionDao workflowNodePermissionDao;
    @Resource
    private AuthService authService;

    @Override
    public int doDeleteByDefine(String id) {
        Example example = new Example(WorkflowNodePermission.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("tenantId", EnvUtil.getTenantId())
                .andEqualTo("wfId", id);
        return workflowNodePermissionDao.deleteByExample(example);
    }

    @Override
    public List<WorkflowNodePermission> selectByNode(WorkflowNode node) {
        Example example = new Example(WorkflowNodePermission.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("tenantId", EnvUtil.getTenantId())
                .andEqualTo("wfNodeId", node.getId());
        return workflowNodePermissionDao.selectByExample(example);
    }

    /**
     * 解析出权限对应的用户
     *
     * @param item
     * @param entity
     * @return
     */
    @Override
    public List<User> parsePermissionUser(WorkflowNodePermission item, Workflow entity) {
        List<User> users = Lists.newArrayList();
        if (Const.Bool.isTrue(item.getByApply())) {
            // 通过申请者
            if (Const.Bool.isTrue(item.getOfDept())) {
                // 的所在部门
                if (StringKit.isNotEmpty(item.getOfPosition())) {
                    // 指定岗位
                    byDeptPosition(item, entity, users);
                }
            } else {
                byApply(entity, users);
            }
        } else if (StringKit.isNotEmpty(item.getByRole())) {
            byRole(item, users);
        } else if (StringKit.isNotEmpty(item.getByFormDept())) {
            // 表单指定的部门
            if (StringKit.isNotEmpty(item.getOfPosition())) {
                // 的指定岗位
                byFormDept(item, entity, users);
            }
        } else if (StringKit.isNotEmpty(item.getByFormUser())) {
            // 表单指定的用户
            byFormUser(item, entity, users);
        }
        return users;
    }

    private void byFormUser(WorkflowNodePermission item, Workflow entity, List<User> users) {
        String field = item.getByFormUser();
        Object value = BeanUtils.getBeanProperty(entity, field);
        if (value == null) {
            return;
        }
        if (value instanceof String) {
            String json = (String) value;
            if (json.startsWith(JSON_OBJECT_PREFIX)) {
                JSONObject obj = JSON.parseObject((String) value);
                users.add(coverToUser(obj.getString(BaseEntity.PK), obj.getString(NAME)));
            } else if (json.startsWith(JSON_ARRAY_PREFIX)) {
                JSONArray array = JSON.parseArray(json);
                array.forEach(obj -> users.add(coverToUser((JSONObject) obj)));
            } else {
                users.add(coverToUser(json, null));
            }
        } else if (value instanceof BaseEntity) {
            users.add(coverToUser((BaseEntity) value));
        } else if (value instanceof Collection) {
            ((Collection) value).forEach(obj -> users.add(coverToUser((BaseEntity) obj)));
        }
    }

    private void byFormDept(WorkflowNodePermission item, Workflow entity, List<User> users) {
        String field = item.getByFormDept();
        Object value = BeanUtils.getBeanProperty(entity, field);
        if (value == null) {
            return;
        }
        String deptId = null;
        if (value instanceof String) {
            String json = (String) value;
            if (json.startsWith(JSON_OBJECT_PREFIX)) {
                deptId = JSON.parseObject(json).getString(BaseEntity.PK);
            } else {
                deptId = (String) value;
            }
        } else if (value instanceof BaseEntity) {
            deptId = ((BaseEntity) value).getId();
        }

        List<User> result = authService
                .getUsersByDeptAndPosition(deptId, item.getOfPosition());
        if (CollectionKit.isNotEmpty(result)) {
            users.addAll(result);
        }
    }

    private void byApply(Workflow entity, List<User> users) {
        users.add(coverToUser(entity.getApplyId(), entity.getApplyDeptName()));
    }

    private void byDeptPosition(WorkflowNodePermission item, Workflow entity, List<User> users) {
        List<User> result = authService
                .getUsersByDeptAndPosition(entity.getApplyDeptId(), item.getOfPosition());
        if (CollectionKit.isNotEmpty(result)) {
            users.addAll(result);
        }
    }

    private void byRole(WorkflowNodePermission item, List<User> users) {
        List<User> result = authService.getUserByRole(item.getByRole());
        if (CollectionKit.isNotEmpty(result)) {
            users.addAll(result);
        }
    }

    private User coverToUser(BaseEntity value) {
        String id = value.getId();
        return coverToUser(id, (String) BeanUtils.getBeanProperty(value, NAME));
    }

    private User coverToUser(String id, String name) {
        User user = new User();
        user.setId(id);
        user.setName(name);
        return user;
    }

    private User coverToUser(JSONObject obj) {
        User user = new User();
        user.setId(obj.getString(BaseEntity.PK));
        user.setName(obj.getString(NAME));
        return user;
    }
}
